//@author A0080442N
#include "QuickAddStringParser.h"

QuickAddStringParser::QuickAddStringParser() {
	_splitString.clear();
}

void QuickAddStringParser::parseString(string userInput, string &activity, string &date) {
	assert(!userInput.empty());
	_splitString.clear();
	size_t foundOpen, foundClosed;

	foundOpen = userInput.find(OPEN_SQUARE_BRACKET);
	foundClosed = userInput.find(CLOSED_SQUARE_BRACKET);
	if (foundOpen != string::npos || foundClosed != string::npos) {
		throw INVALID_REQUEST;
	}

	string tempWord;
	tempWord.clear();
	while (!userInput.empty()) {
		if (userInput[INITIAL_VALUE] != WHITE_SPACE) {
			tempWord = tempWord + userInput[INITIAL_VALUE];
			userInput.erase(userInput.begin());
		} else {
			_splitString.push_back(tempWord);
			userInput.erase(userInput.begin());
			tempWord.clear();
		}
	}

	if (!tempWord.empty()) {
		_splitString.push_back(tempWord);
		tempWord.clear();
	}

	try {
		analyseString(activity, date);
	} catch (string error) {
		throw;
	}
}

void QuickAddStringParser::analyseString(string &activity, string &date) {
	bool hasPreviousKeyWord = false, hasDate = false;
	string keyWord;
	activity.clear();
	date = EMPTY_FIELD;
	int size = _splitString.size();

	for (int i = INITIAL_VALUE; i < size; i++) {
		if (isDayKeyword(_splitString[i]) && hasDate) {
			throw TOO_MANY_DATES;
		} else if (isKeyword(_splitString[i]) && !hasDate) {
			if (_splitString[i] == today || _splitString[i] == Today) {
				hasDate = true;
				date = setDateForToday();
				i--;
			} else if (_splitString[i] == Tomorrow || _splitString[i] == tomorrow || _splitString[i] == tmr || _splitString[i] == tml) {
				hasDate = true;
				date = setDateForTomorrow();
				i--;
			} else if ((_splitString[i] == thisString || _splitString[i] == This) && (i + SHIFT_INDEX_BY_ONE < size)) {
				hasDate = setDateForThisOrNext(thisString, _splitString[i + SHIFT_INDEX_BY_ONE], date);
			} else if ((_splitString[i] == nextString || _splitString[i] == Next) && (i + SHIFT_INDEX_BY_ONE < size)) {
				hasDate = setDateForThisOrNext(nextString, _splitString[i + SHIFT_INDEX_BY_ONE], date);
			} else if ((_splitString[i] == On || _splitString[i] == on) && (i + SHIFT_INDEX_BY_ONE < size)) {
				hasDate = setDateForOn(_splitString[i + SHIFT_INDEX_BY_ONE], date);
			}
			if (hasDate) {
				i++;
			} else {
				appendToActivity(activity, _splitString[i]);
			}
		} else {
			appendToActivity(activity, _splitString[i]);
		}
	}
	if (!activity.empty()) {
		activity.erase(activity.end() - SHIFT_INDEX_BY_ONE);
	} else {
		activity = EMPTY_FIELD;
	}
}

string QuickAddStringParser::setDateForToday() {
	Date today;
	today.setLocalDate();
	return today.getDisplay();
}

string QuickAddStringParser::setDateForTomorrow() {
	Date tomorrow;
	tomorrow.setLocalDate();
	tomorrow.addNumberofDays(SHIFT_INDEX_BY_ONE);
	return tomorrow.getDisplay();
}

bool QuickAddStringParser::setDateForOn(string keyword, string &date) {
	Date myDate;
	try {
		int keywordInt = atoi(keyword.c_str());
		myDate.setDate(keywordInt);
		date = keyword;
		return true;
	} catch (string error) {
		return setDateForThisOrNext(thisString, keyword, date);
	}
}

bool QuickAddStringParser::setDateForThisOrNext(string keyword, string nextKeyword, string &date) {
	Date myDate;
	myDate.setLocalDate();
	int day = INVALID_INDEX;
	if (nextKeyword == monday || nextKeyword == Monday || nextKeyword == mon) {
		day = ONE;
	}
	if (nextKeyword == tuesday || nextKeyword == Tuesday || nextKeyword == tues) {
		day = TWO;
	}
	if (nextKeyword == wednesday || nextKeyword == Wednesday || nextKeyword == wed) {
		day = THREE;
	}
	if (nextKeyword == thursday || nextKeyword == Thursday || nextKeyword == thurs) {
		day = FOUR;
	}
	if (nextKeyword == friday || nextKeyword == Friday || nextKeyword == fri) {
		day = FIVE;
	}
	if (nextKeyword == saturday || nextKeyword == Saturday || nextKeyword == sat) {
		day = SIX;
	}
	if (nextKeyword == sunday || nextKeyword == Sunday || nextKeyword == sun) {
		day = SEVEN;
	}
	if (day != INVALID_INDEX) {
		int currentDay = myDate.getDayOfWeek();
		if (keyword == nextString) {
			day = day + SEVEN;
		}
		if (day > currentDay) {
			myDate.addNumberofDays(day - currentDay);
		} else {
			myDate.minusNumberofDays(currentDay - day);
		}
		date = myDate.getDisplay();
		return true;
	}
	return false;
}

bool QuickAddStringParser::isKeyword(string keyword) {
	return (keyword == today || keyword == Today ||
		keyword == Tomorrow || keyword == tomorrow || keyword == tmr || keyword == tml ||
		keyword == thisString || keyword == This ||
		keyword == nextString || keyword == Next ||
		keyword == On || keyword == on);
}

bool QuickAddStringParser::isDayKeyword(string keyword) {
	return (keyword == monday || keyword == Monday || keyword == mon ||
		keyword == tuesday || keyword == Tuesday || keyword == tues ||
		keyword == wednesday || keyword == Wednesday || keyword == wed ||
		keyword == thursday || keyword == Thursday || keyword == thurs ||
		keyword == friday || keyword == Friday || keyword == fri ||
		keyword == saturday || keyword == Saturday || keyword == sat ||
		keyword == sunday || keyword == Sunday || keyword == sun ||
		keyword == today || keyword == Today ||
		keyword == Tomorrow || keyword == tomorrow || keyword == tmr || keyword == tml);
}

void QuickAddStringParser::appendToActivity(string &activity, string keyword) {
	activity = activity + keyword + WHITE_SPACE;
}